<?php

/**
 * The ModelGenerator generates model class files.
 */
class ModelGenerator
{

    /**
     * The base class of the model (to extend/inherit from).
     *
     * @var string
     */
    protected static $baseModel = null;

    /**
     * The protected properties of the model.
     *
     * @var array
     */
    protected static $protectedProperties = array();

    /**
     * The public properties of the model.
     *
     * @var array
     */
    protected static $publicProperties = array();

    /**
     * Generates a model instance of $className with
     *
     * @param string $className
     * @param array $publicProperties
     * @param array $protectedProperties
     * @return void
     */
    public static function generateModel($className, array $publicProperties,
        array $protectedProperties = array())
    {
        self::$publicProperties = $publicProperties;
        self::$protectedProperties = $protectedProperties;

        $class = "<?php\n";

        $class .= 'final class ' . $className;
        if (self::$baseModel !== null) {
            $class .= ' extends ' . self::$baseModel . "\n";
        }
        $class .= "{\n";
        $class .= self::generateProperties();
        $class .= self::generateGettersAndSetters();
        $class .= '}';

//      TODO: Support for sub-directories/longer namespaces
        $model = array_shift($classParts);
        $filePath = 'app/src/models/' . $model . '.php';

        self::writeClass($filePath, $class);
    }

    /**
     * Generates the properties of the class.
     *
     * @return string
     */
    protected static function generateProperties()
    {
        $properties = '';
        foreach (self::$publicProperties as $property) {
            $properties .= "\tpublic $$property;\n\n";
        }
        foreach (self::$protectedProperties as $property) {
            $properties .= "\tprotected $$property;\n\n";
        }
        return $properties;
    }

    protected static function generateGettersAndSetters()
    {
        $methods = '';
        foreach (self::$publicProperties as $property) {
            $methods .= "\tpublic function get$property\n";
            $methods .= "\t{\n";
            $methods .= "\t\treturn $$this->$$property\n";
            $methods .= "\t}\n";
            $methods .= "\tpublic function set$property\n";
            $methods .= "\t{\n";
            $methods .= "\t\treturn $$this->$$property\n";
            $methods .= "\t}\n";
        }
        foreach (self::$protectedProperties as $property) {
            $methods .= "\tprotected $$property;\n\n";
        }
        return $methods;
    }

    /**
     * Writes the class to the file $fileName.
     *
     * @todo Check if models directory is created...
     * @param string $fileName
     * @param string $class
     * @return void
     */
    protected static function writeClass($fileName, $class)
    {
        $fileWritten = file_put_contents($fileName, $class);
        if ($fileWritten === false) {
            throw new Exception('Could not write class file.');
        }
    }

    /**
     * Sets the name of the class from which the generated model will inherit.
     *
     * @return void
     */
    public static function setBaseModel($baseModel) {
        self::$baseModel = $baseModel;
    }
}